// @(#)proto.hh
// Time-stamp: <2009-02-03 13:17:46 root>
// Copyright 2008 Julian Qian
// Author: root@localhost.localdomain
// Version: $Id: proto.hh,v 0.0 2008/11/16 11:29:15 root Exp $
// Keywords: 

#ifndef _PROTO_H
#define _PROTO_H 1

#include "common.hh"

extern "C" {
#include <time.h>
}

#define AUTH_TRUE 1
#define AUTH_FALSE 0
#define AUTH_NULL -1

class Proto {
public:
    Proto(char *dev_buf, ip_t dev_ip, bool dev_auth);
    Proto(const Proto& pro);
    Proto();
    virtual ~Proto();

    inline stat_t get_stat(){
        return _stat;
    }
    inline devid_t get_devid(){
        return _devid;
    }
    inline ip_t get_ip(){
        return _ip;
    }
    inline alarm_t get_alarm(){
        return _alarm;
    }
    inline int get_up_time(){
        return _up_time;
    }
    inline int get_sequence(){
        return _sequence;
    }
    inline int get_auth(){
        return _auth;
    }
    
    void buffer_init(char *buf);
    
    inline char* get_buffer(){
        return bufptr;
    }
    
    inline int reply_length(){
        return PROTO_LENG;
    }
    bool do_reply();
    bool do_alarm();
    inline bool is_reset(){
        return (_stat == STAT_RESET)?true : false;
    }
    inline bool is_omit(){
        return (_stat == STAT_TIMER || _stat == STAT_NULLL)?true : false;
    }
    inline bool is_null(){
        if(_devid){
            return false;
        }
        return true;
    }
    inline bool is_auth(){
        return _auth;
    }
    
    inline bool expired(){
        int curr_tm = (int)time(NULL);
        // expired if over 15 min
        if(curr_tm - _up_time > 15*60){
            return true;
        }
        return false;        
    }

    char* composite(char* buf,devid_t devid, int seq, type_t type, alarm_t alarm);

    inline int up_time(){
        return _up_time = (int)time(NULL);
    }
    inline void set_stat(stat_t st){
        _stat = st;
    }
    inline void set_auth(bool au){
        _auth = au;
    }
    inline void set_alarm(alarm_t ala){
        _alarm = ala;
    }

    inline bool equal(const Proto& pr){
        if(pr._ip == _ip  &&
           pr._stat == _stat ){
            return true;
        }
        return false;
    }
    inline void copy(Proto& pr){
        _ip = pr._ip;
        _alarm = pr._alarm;
        _stat = pr._stat;
        _up_time = pr._up_time; // TODO: or up_time()?
        _sequence = pr._sequence;
        _auth = pr._auth;
    }

    Proto& operator = (const Proto& pro){
        // devid
        _devid = pro._devid;
        _alarm = pro._alarm;
        _ip = pro._ip;
        _stat = pro._stat;
    
        _up_time = pro._up_time;
        _sequence = pro._sequence;

        _auth = pro._auth;

        bufptr = pro.bufptr;

        return *this;
    }
    
private:
    stat_t get_buf_stat();
    void set_buf_stat(char type, char data);
    int char2int(char *buf, int len);
    void int2char(unsigned int intt, char* buf, int len);
        
    devid_t _devid;
    ip_t _ip;
    alarm_t _alarm;
    stat_t _stat;
    int _up_time; // timestamp
    int _sequence; // sequence number, 0~65535
    
    char *bufptr;
    // char _proto[PROTO_LENG];

    bool _auth;

    // char _buffer[PROTO_LENG];
};

#endif /* _PROTO_H */

